File: target_io.c

    1   /* Copyright 2011-2013 The MathWorks, Inc. */
    2   #include <stdio.h> /* sprintf */
    3   #include <stdarg.h> /* variable argument lists */
    4   #include "xil_interface_common.h"
    5   #include "xil_data_stream.h"
    6   #include "xil_common.h"
    7   #include "target_io.h"
    8   #include "rtwtypes.h"
    9   
   10   /* test for ISO C99 or greater, which supports vsnprintf 
   11    * 
   12    * WARNING: if the compiler is ANSI C90 then we use vsprintf instead.
   13    * Therefore, it is possible to overrun the buffer so the 
   14    * caller must take care not to exceed the buffer size! 
   15    */
   16   #if __STDC_VERSION__ >= 199901L
   17   #define VSNPRINTF_AVAILABLE
   18   #endif
   19   
   20   #ifndef TARGET_IO_BUFFER_SIZE
   21   /* default buffer size is large enough for most use cases */
   22   #define TARGET_IO_BUFFER_SIZE 64 
   23   #endif
   24   
   25   #ifndef TARGET_IO_MAX_FILE_ID
   26   /* -1 avoids warning about the comparison that is done
   27    * in targetFopen 
   28    *
   29    * note that MAX_uint16_T will be limited to uint16 max
   30    * even when portable word sizes maps uint16 to a larger 
   31    * type such as uint32 on the SHARC */
   32   #define TARGET_IO_MAX_FILE_ID (MAX_uint16_T - 1)
   33   #endif
   34   
   35   typedef enum {TARGET_IO_SUCCESS=0,
   36                 TARGET_IO_BUFFER_TRUNC } TARGET_IO_ERROR_ID;
   37   
   38   static char targetStdioBuffer[TARGET_IO_BUFFER_SIZE];
   39   #ifdef HOST_WORD_ADDRESSABLE_TESTING
   40   static MemUnit_T hostWordStdioBuffer[TARGET_IO_BUFFER_SIZE];
   41   #endif
   42   
   43   /* fid is the file id on target and is limited to TARGET_IO_MAX_FILE_ID */
   44   static uint16_T fid = 0;
   45   
   46   /* call xilWriteData and check for errors */
   47   static void targetWriteDataWithErrorCheck(const MemUnit_T *, uint32_T);
   48   #ifdef HOST_WORD_ADDRESSABLE_TESTING
   49   static void targetWriteDataWithCharToMemUnitWidening(const char *, MemUnit_T *, uint16_T);
   50   #endif /* HOST_WORD_ADDRESSABLE_TESTING */
   51   
   52   void targetWriteDataWithErrorCheck(const MemUnit_T * data, uint32_T size) {
   53      if (xilWriteData(data, size) != XIL_DATA_STREAM_SUCCESS) {
   54         for (;;) {
   55            /* fatal comms error */
   56         }
   57      }
   58   }
   59   
   60   #ifdef HOST_WORD_ADDRESSABLE_TESTING
   61   static void targetWriteDataWithCharToMemUnitWidening(const char *pCharBuff, MemUnit_T *pMemUnitBuff, uint16_T buffSize) {
   62      uint16_T i;
   63      for(i=0;i<buffSize;i++) {
   64         pMemUnitBuff[i] = (MemUnit_T) pCharBuff[i];
   65      }
   66      targetWriteDataWithErrorCheck(pMemUnitBuff, buffSize * sizeof(MemUnit_T));
   67   }
   68   #endif
   69   
   70   /* Forward a printf back to the host machine
   71    *
   72    * Printf size must not exceed the TARGET_IO_BUFFER_SIZE
   73    * otherwise overflow will occur. 
   74    */
   75   void targetPrintf(const char * fmt, ...) {   
   76      va_list argptr;
   77      uint16_T printSize;
   78      int vsPrintSize;
   79      MemUnit_T responseId = XIL_RESPONSE_PRINTF;
   80      MemUnit_T errorId = TARGET_IO_SUCCESS;
   81   
   82      va_start(argptr, fmt);
   83   #ifdef VSNPRINTF_AVAILABLE
   84      /* size arg includes '\0', return value does not */
   85      vsPrintSize = vsnprintf(&targetStdioBuffer[0], TARGET_IO_BUFFER_SIZE, fmt, argptr);
   86   #else
   87      vsPrintSize = vsprintf(&targetStdioBuffer[0], fmt, argptr);
   88   #endif   
   89      if ((vsPrintSize < 0) || (vsPrintSize >= TARGET_IO_BUFFER_SIZE)) {
   90         /* set error id if error or buffer overruns */      
   91         errorId = TARGET_IO_BUFFER_TRUNC;
   92         /* do not send any data */
   93         printSize = 0;
   94      } else {
   95         /* add one for the terminating null character */
   96         printSize = (uint16_T) vsPrintSize + 1;   		
   97      }
   98      va_end(argptr);
   99   
  100      /* send response id */
  101      targetWriteDataWithErrorCheck(&responseId, sizeof(responseId));
  102      /* send error id */
  103      targetWriteDataWithErrorCheck(&errorId, sizeof(errorId));
  104      /* send printSize */
  105      targetWriteDataWithErrorCheck((MemUnit_T *) &printSize, sizeof(printSize));
  106      /* send data */
  107      if (printSize > 0) {
  108   #ifdef HOST_WORD_ADDRESSABLE_TESTING
  109         targetWriteDataWithCharToMemUnitWidening(&targetStdioBuffer[0], &hostWordStdioBuffer[0], printSize);
  110   #else
  111         targetWriteDataWithErrorCheck((MemUnit_T *)&targetStdioBuffer[0], printSize);
  112   #endif
  113      }
  114      return;
  115   }
  116   
  117   
  118   /* Forward a fopen back to the host.
  119    *
  120    * fid is used on target to act as a valid 
  121    * "file descriptor".
  122    */
  123   unsigned short targetFopen(const char * fileName) {
  124      uint16_T fileNameSize;
  125      MemUnit_T responseId = XIL_RESPONSE_FOPEN;
  126   
  127      /* size of file name string */
  128      fileNameSize = (uint16_T) strlen(fileName);
  129   
  130      /* add one for the terminating null character */
  131      fileNameSize++;
  132    
  133      /* check bounds and reset to 0 if necessary which will trigger an error 
  134       * on the host */
  135      if(fid > TARGET_IO_MAX_FILE_ID) {
  136         fid = 0;
  137      }
  138      /* send response id */
  139      targetWriteDataWithErrorCheck(&responseId, sizeof(responseId));
  140      /* send file id */
  141      targetWriteDataWithErrorCheck((MemUnit_T *)&fid, sizeof(fid));
  142      /* send size of file name string */
  143      targetWriteDataWithErrorCheck((MemUnit_T *)&fileNameSize, sizeof(fileNameSize));
  144   #ifdef HOST_WORD_ADDRESSABLE_TESTING
  145      /* in case the total size is bigger than the hostWordStdioBuffer, send in 
  146       * multiple chunks */
  147      {      
  148         while (fileNameSize > 0) {
  149            uint16_T transferSize = MIN(fileNameSize, TARGET_IO_BUFFER_SIZE);
  150            /* send file name string */
  151            targetWriteDataWithCharToMemUnitWidening(fileName, &hostWordStdioBuffer[0], transferSize);   
  152            fileNameSize -= transferSize;
  153            fileName += transferSize;
  154         }
  155      }
  156   #else
  157      /* send file name string */
  158      targetWriteDataWithErrorCheck((const MemUnit_T *)fileName, fileNameSize);
  159   #endif
  160   
  161      /* return fid, THEN increment it */
  162      return (unsigned short) (fid++); /* unsigned short is at least 16-bits
  163                                        * wide. See header file for more
  164                                        * information on why this cast is
  165                                        * required. */
  166   }
  167   
  168   void targetFprintf(unsigned short targetFid, const char * fmt, ...) {
  169      va_list argptr;
  170      uint16_T fprintSize;
  171      int vsFprintSize;
  172      MemUnit_T responseId = XIL_RESPONSE_FPRINTF;
  173      MemUnit_T errorId = TARGET_IO_SUCCESS;
  174      const uint16_T targetFid16 = (uint16_T) targetFid;  /* We only use the
  175                                                           * lowermost 16 bits of
  176                                                           * targetFid. unsigned
  177                                                           * int is guaranteed to
  178                                                           * be at least 16 bits
  179                                                           * wide. See header file
  180                                                           * for more information
  181                                                           * on why this cast is
  182                                                           * required. */
  183   
  184      va_start(argptr, fmt);
  185   #ifdef VSNPRINTF_AVAILABLE
  186      /* size arg includes '\0', return value does not */
  187      vsFprintSize = vsnprintf(&targetStdioBuffer[0], TARGET_IO_BUFFER_SIZE, fmt, argptr);
  188   #else
  189      vsFprintSize = vsprintf(&targetStdioBuffer[0], fmt, argptr);
  190   #endif   
  191      if ((vsFprintSize < 0) || (vsFprintSize >= TARGET_IO_BUFFER_SIZE)) {
  192         /* set error id if error or buffer overruns */      
  193         errorId = TARGET_IO_BUFFER_TRUNC;
  194         /* do not send any data */
  195         fprintSize = 0;
  196      } else {
  197         /* add one for the terminating null character */
  198         fprintSize = (uint16_T) vsFprintSize + 1;
  199      }
  200      va_end(argptr);
  201   
  202      /* send response id */
  203      targetWriteDataWithErrorCheck(&responseId, sizeof(responseId));
  204      /* send error id */
  205      targetWriteDataWithErrorCheck(&errorId, sizeof(errorId));
  206      /* send file id*/
  207      targetWriteDataWithErrorCheck((MemUnit_T *)&targetFid16, 
  208                                    sizeof(targetFid16));
  209      /* send fprintSize */
  210      targetWriteDataWithErrorCheck((MemUnit_T *)&fprintSize, sizeof(fprintSize));
  211      if (fprintSize > 0) {
  212   #ifdef HOST_WORD_ADDRESSABLE_TESTING
  213         /* send data */
  214         targetWriteDataWithCharToMemUnitWidening(&targetStdioBuffer[0], &hostWordStdioBuffer[0], fprintSize);
  215   #else
  216         /* send data */
  217         targetWriteDataWithErrorCheck((MemUnit_T *)&targetStdioBuffer[0], fprintSize);
  218   #endif
  219      }
  220      return;
  221   }
  222